/**
 * 客人数据模型类
 * 
 * 这个类用来表示酒店的一位客人，包含客人的所有个人信息
 * 这是一个典型的Java实体类（Entity Class），用于数据存储和传输
 * 
 * 主要功能：
 * 1. 存储客人的个人信息（ID、姓名、身份证、电话、地址）
 * 2. 提供访问和修改这些信息的方法（getter和setter）
 * 3. 提供数据持久化方法（保存到文件和从文件读取）
 * 4. 提供友好的字符串显示格式
 * 
 * 设计模式：这个类遵循JavaBean规范
 * - 所有属性都是private（私有的）
 * - 提供public的getter和setter方法
 * - 有一个public的构造方法
 */
public class Guest {
    // ==================== 成员变量定义 ====================
    // 所有成员变量都声明为private，这是封装的体现
    // 封装是面向对象编程的三大特性之一（封装、继承、多态）

    private String guestId; // 客人唯一标识ID，用于区分不同的客人
    private String name; // 客人姓名
    private String idCard; // 身份证号码
    private String phone; // 联系电话
    private String address; // 家庭住址

    /**
     * 构造方法 - 创建Guest对象时必须提供所有必要信息
     * 
     * 构造方法的特点：
     * 1. 方法名与类名完全相同
     * 2. 没有返回值类型（连void都不写）
     * 3. 在使用new关键字创建对象时自动调用
     * 4. 用于初始化对象的状态
     * 
     * @param guestId 客人ID - 通常是系统自动生成的唯一标识
     * @param name    客人姓名 - 真实姓名，用于登记
     * @param idCard  身份证号 - 用于身份验证
     * @param phone   联系电话 - 用于联系客人
     * @param address 家庭地址 - 客人的居住地址
     */
    public Guest(String guestId, String name, String idCard, String phone, String address) {
        // this关键字的作用：
        // 1. 指向当前对象
        // 2. 区分成员变量和参数（当参数名和成员变量名相同时）
        this.guestId = guestId;
        this.name = name;
        this.idCard = idCard;
        this.phone = phone;
        this.address = address;
    }

    // ==================== Getter方法区域 ====================
    // Getter方法用于获取私有成员变量的值
    // 这些方法提供了对私有数据的只读访问
    // 方法命名规范：get + 属性名（首字母大写）

    /**
     * 获取客人ID
     * 
     * 客人ID是客人的唯一标识，通常在客人第一次入住时生成
     * 后续的所有操作都通过这个ID来识别客人
     * 
     * @return 客人的唯一标识ID
     */
    public String getGuestId() {
        return guestId;
    }

    /**
     * 获取客人姓名
     * 
     * @return 客人的真实姓名
     */
    public String getName() {
        return name;
    }

    /**
     * 获取身份证号码
     * 
     * 身份证号是客人身份的重要凭证
     * 在实际应用中，这类敏感信息需要加密存储
     * 
     * @return 客人的身份证号码
     */
    public String getIdCard() {
        return idCard;
    }

    /**
     * 获取联系电话
     * 
     * @return 客人的联系电话
     */
    public String getPhone() {
        return phone;
    }

    /**
     * 获取家庭地址
     * 
     * @return 客人的家庭住址
     */
    public String getAddress() {
        return address;
    }

    // ==================== Setter方法区域 ====================
    // Setter方法用于设置私有成员变量的值
    // 这些方法提供了对私有数据的写入访问
    // 方法命名规范：set + 属性名（首字母大写）
    // 在实际项目中，setter方法中通常会加入数据验证逻辑

    /**
     * 设置客人ID
     * 
     * 注意：在实际应用中，客人ID通常不允许修改
     * 这里提供setter方法主要是为了完整性
     * 
     * @param guestId 新的客人ID
     */
    public void setGuestId(String guestId) {
        this.guestId = guestId;
    }

    /**
     * 设置客人姓名
     * 
     * @param name 新的客人姓名
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 设置身份证号码
     * 
     * 在实际应用中，这里应该添加身份证号码格式验证
     * 例如：检查长度、检查数字格式等
     * 
     * @param idCard 新的身份证号码
     */
    public void setIdCard(String idCard) {
        this.idCard = idCard;
    }

    /**
     * 设置联系电话
     * 
     * 在实际应用中，这里应该添加电话号码格式验证
     * 例如：检查是否为11位数字、是否以1开头等
     * 
     * @param phone 新的联系电话
     */
    public void setPhone(String phone) {
        this.phone = phone;
    }

    /**
     * 设置家庭地址
     * 
     * @param address 新的家庭地址
     */
    public void setAddress(String address) {
        this.address = address;
    }

    // ==================== 数据持久化方法 ====================
    // 这些方法用于将对象数据保存到文件或从文件中恢复对象

    /**
     * 将客人信息转换为文件存储格式
     * 
     * 这个方法将客人的所有信息按照特定格式组合成一个字符串
     * 使用"|"作为字段分隔符，这样可以方便地保存到文本文件中
     * 
     * 数据格式：客人ID|姓名|身份证|电话|地址
     * 示例：G123456|张三|110101199001011234|13800138000|北京市朝阳区
     * 
     * 为什么选择"|"作为分隔符？
     * 1. "|"在姓名、地址等文本中很少出现，避免冲突
     * 2. 比逗号更安全（地址中可能包含逗号）
     * 3. 比制表符更明显，便于调试
     * 
     * @return 格式化的字符串，可直接写入文件
     */
    public String toFileString() {
        // 字符串连接：使用"+"操作符连接多个字符串
        // Java会自动处理字符串连接的内存管理
        return guestId + "|" + name + "|" + idCard + "|" + phone + "|" + address;
    }

    /**
     * 从文件格式的字符串创建Guest对象
     * 
     * 这是一个静态方法（static method）
     * 静态方法的特点：
     * 1. 属于类而不是对象，可以直接通过类名调用
     * 2. 不能访问非静态的成员变量和方法
     * 3. 通常用于工具方法或工厂方法
     * 
     * 这个方法的作用是解析从文件中读取的字符串，创建Guest对象
     * 这种设计模式叫做"工厂方法"，用于创建对象
     * 
     * @param line 从文件中读取的一行数据，格式：ID|姓名|身份证|电话|地址
     * @return 创建的Guest对象，如果数据格式错误则返回null
     */
    public static Guest fromFileString(String line) {
        // 字符串分割：split()方法根据指定的分隔符分割字符串
        // 返回一个字符串数组，包含分割后的各个部分

        // "\\|" 是正则表达式，表示以"|"字符分割
        // 为什么要写成"\\|"？
        // 1. "|"在正则表达式中是特殊字符，表示"或"的意思
        // 2. 要表示字面意思的"|"字符，需要用反斜杠转义
        // 3. 在Java字符串中，反斜杠本身也需要转义，所以写成"\\"
        String[] parts = line.split("\\|");

        // 数据验证：检查分割后的数组长度
        // 如果长度不是5，说明数据格式不正确
        if (parts.length == 5) {
            // 创建并返回新的Guest对象
            // parts[0]是客人ID，parts[1]是姓名，以此类推
            return new Guest(parts[0], parts[1], parts[2], parts[3], parts[4]);
        }

        // 如果数据格式不正确，返回null
        // 调用这个方法的代码需要检查返回值是否为null
        return null;
    }

    /**
     * 重写toString()方法
     * 
     * toString()方法是Object类的方法，所有Java类都继承自Object类
     * 
     * @Override注解表示我们要重写（覆盖）父类的方法
     * 
     *                             重写toString()的好处：
     *                             1. 当我们打印对象时，会自动调用这个方法
     *                             2. 在调试时可以方便地查看对象的内容
     *                             3. 提供对象的字符串表示形式
     * 
     *                             如果不重写toString()，打印对象时会显示类似这样的内容：
     *                             Guest@1a2b3c4d（类名@哈希码）
     * 
     * @return 客人信息的友好显示格式
     */
    @Override
    public String toString() {
        // 返回一个包含主要信息的字符串
        // 注意：为了保护隐私，这里没有显示完整的身份证号
        return "客人ID: " + guestId + ", 姓名: " + name +
                ", 身份证: " + idCard + ", 电话: " + phone;
    }
}